﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Input.Manipulations;
using Microsoft.Surface.Presentation.Input;
using ZOIL.Framework.Core;
using ZOIL.Framework.Presentation;

namespace ZOIL.Library.Behaviors
{
    public static class ZObjectResizeBehavior
    {
        #region IsResizable attached property (for setting resizing behavior active or unactive)

        public static DependencyProperty IsResizableProperty = DependencyProperty.RegisterAttached("IsResizable",
                                                                                                   typeof (bool),
                                                                                                   typeof (ZObjectResizeBehavior),
                                                                                                   new FrameworkPropertyMetadata(false,
                                                                                                                                 IsResizableChanged));

        private static Dictionary<FrameworkElement, ZObjectResizingInformation> ElementsBeingResized =
            new Dictionary<FrameworkElement, ZObjectResizingInformation>();

        #region mouse handling

        private static Adorner currentAdorner;
        private static AdornerLayer currentAdornerLayer;

        private static void OnMouseEnter(object sender, MouseEventArgs e)
        {
            var element = sender as ZComponent;

            if (element != null)
            {
                AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
                if (layer != null)
                {
                    var resizeAdorner = new ZObjectResizeAdorner(element);
                    layer.Add(resizeAdorner);
                }
            }
        }

        private static void OnMouseLeave(object sender, MouseEventArgs e)
        {
            var element = sender as ZComponent;
            if (element != null)
            {
                AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
                if (layer != null)
                {
                    currentAdornerLayer = layer;
                    IEnumerable<ZObjectResizeAdorner> resizeAdorners = layer.GetAdorners(element).OfType<ZObjectResizeAdorner>();
                    foreach (ZObjectResizeAdorner resizeAdorner in resizeAdorners)
                    {
                        if (resizeAdorner.AdornedElement == element)
                        {
                            if (resizeAdorner.IsMouseOver)
                            {
                                currentAdorner = resizeAdorner;
                                resizeAdorner.MouseLeave += resizeAdorner_MouseLeave;
                                return;
                            }
                            layer.Remove(resizeAdorner);
                        }
                    }
                }
            }
        }

        private static void resizeAdorner_MouseLeave(object sender, MouseEventArgs e)
        {
            currentAdornerLayer.Remove(currentAdorner);
        }

        #endregion

        private static void IsResizableChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            var element = target as UIElement;

            /* MZ: Commented out due to performance issues
            ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, Mouse.MouseEnterEvent, new MouseEventHandler(OnMouseEnter));
            ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, Mouse.MouseLeaveEvent, new MouseEventHandler(OnMouseLeave));
            */
            //Surface

            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, UIElement.TouchDownEvent, new EventHandler<TouchEventArgs>(ZObjectSurfaceHandler.OnContactDown));
            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, UIElement.TouchDownEvent, new EventHandler<TouchEventArgs>(ZObjectSurface2Handler.OnTouchDown));
            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, UIElement.TouchUpEvent, new EventHandler<TouchEventArgs>(ZObjectSurfaceHandler.OnContactUp));
            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, TouchExtensions.TapGestureEvent, new EventHandler<TouchEventArgs>(ZObjectSurfaceHandler.OnContactTapGesture));
            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, Contacts.ContactChangedEvent, new ContactEventHandler(OnContactChanged));
            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, TouchExtensions.HoldGestureEvent, new EventHandler<TouchEventArgs>(ZObjectSurfaceHandler.OnContactHold));

            //TODO: besseren Weg finden um 2x/3x Registrierung der Events zu verhindern
            if (!ZObjectRotateBehavior.GetIsRotatable(target as UIElement) && !ZObjectDragDropBehavior.GetIsDraggable(target as ZComponent))
            {
                ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, TouchExtensions.TapGestureEvent,
                                       new EventHandler<TouchEventArgs>(ZObjectSurfaceHandler.OnContactTapGesture));
                ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, UIElement.ManipulationStartingEvent,
                                       new EventHandler<ManipulationStartingEventArgs>(ZObjectSurface2Handler.ManipulationStarting));
                ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, UIElement.ManipulationDeltaEvent,
                                       new EventHandler<ManipulationDeltaEventArgs>(ZObjectSurface2Handler.ManipulationDelta));
                ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, UIElement.ManipulationInertiaStartingEvent,
                                       new EventHandler<ManipulationInertiaStartingEventArgs>(ZObjectSurface2Handler.ManipulationInertiaStarting));
                ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, UIElement.ManipulationCompletedEvent,
                                       new EventHandler<ManipulationCompletedEventArgs>(ZObjectSurface2Handler.ManipulationCompleted));
                ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, UIElement.TouchDownEvent,
                                       new EventHandler<TouchEventArgs>(ZObjectSurface2Handler.OnTouchDown));
            }

            //TODO: enable these handlers, so the event handling with processors is cleaner
            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, Contacts.ContactUpEvent, new ContactEventHandler(ZObjectSurfaceHandler.OnContactUp));
            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, Contacts.GotContactCaptureEvent, new ContactEventHandler(ZObjectSurfaceHandler.OnGotContactCapture));
            //ZBehavior.HandleChange(e.OldValue, e.NewValue, target as UIElement, Contacts.LostContactCaptureEvent, new ContactEventHandler(ZObjectSurfaceHandler.OnLostContactCapture));

            //Wii
        }

        //#region surface handling

        //private static void OnContactDown(object sender, ContactEventArgs e)
        //{
        //    FrameworkElement element = sender as FrameworkElement;
        //    if (element != null)
        //    {
        //        ZObjectResizingInformation info = null;
        //        if (!ElementsBeingResized.ContainsKey(element))
        //        {
        //            info = new ZObjectResizingInformation(element);
        //            ElementsBeingResized[element] = info;
        //            info.ManipulationProcessor.Affine2DManipulationDelta += new EventHandler<Affine2DOperationDeltaEventArgs>(ManipulationProcessor_Affine2DManipulationDelta);
        //            info.ManipulationProcessor.Affine2DManipulationCompleted += new EventHandler<Affine2DOperationCompletedEventArgs>(ManipulationProcessor_Affine2DManipulationCompleted);
        //        }
        //        else
        //        {
        //            info = ElementsBeingResized[element];
        //        }
        //        info.ContactEvents.Add(e);
        //        info.ManipulationProcessor.BeginTrack(e.Contact);
        //        e.Handled = true;
        //    }
        //}

        //static void ManipulationProcessor_Affine2DManipulationCompleted(object sender, Affine2DOperationCompletedEventArgs e)
        //{
        //    Affine2DManipulationProcessor processor = sender as Affine2DManipulationProcessor;

        //    FrameworkElement fe = processor.Container as FrameworkElement;
        //    if (fe != null)
        //    {
        //        if (ElementsBeingResized.ContainsKey(fe))
        //        {
        //            ElementsBeingResized.Remove(fe);
        //        }
        //    }
        //}

        //static void ManipulationProcessor_Affine2DManipulationDelta(object sender, Affine2DOperationDeltaEventArgs e)
        //{

        //    Affine2DManipulationProcessor processor = sender as Affine2DManipulationProcessor;

        //    FrameworkElement fe = processor.Container as FrameworkElement;
        //    if (fe != null)
        //    {

        //        if (ElementsBeingResized.ContainsKey(fe))
        //        {
        //            ZObjectResizingInformation info = ElementsBeingResized[fe];

        //            Console.WriteLine(e.ScaleDelta);

        //            double oldWidth = info.ElementBeingResized.Width;
        //            double oldHeight = info.ElementBeingResized.Height;

        //            info.ElementBeingResized.Width *= e.ScaleDelta;
        //            info.ElementBeingResized.Height *= e.ScaleDelta;

        //            double xdiff = info.ElementBeingResized.Width - oldWidth;
        //            double ydiff = info.ElementBeingResized.Height - oldHeight;

        //            Canvas.SetLeft(info.ElementBeingResized, Canvas.GetLeft(info.ElementBeingResized) - (xdiff / 2.0));
        //            Canvas.SetTop(info.ElementBeingResized, Canvas.GetTop(info.ElementBeingResized) - (ydiff / 2.0));

        //            foreach (ContactEventArgs args in info.ContactEvents)
        //            {
        //                args.Handled = true;

        //            }

        //        }
        //    }
        //}

        //private static void OnContactChanged(object sender, ContactEventArgs e)
        //{
        //    FrameworkElement element = sender as FrameworkElement;
        //    if (element != null)
        //    {
        //        if(ElementsBeingResized.ContainsKey(element))
        //        {
        //            ZObjectResizingInformation info = ElementsBeingResized[element];
        //            info.ContactEvents.Add(e);
        //        }
        //    }
        //}

        //private static void OnContactLeave(object sender, ContactEventArgs e)
        //{

        //}

        //#endregion

        public static void SetIsResizable(UIElement target, bool value)
        {
            target.SetValue(IsResizableProperty, value);
        }

        public static bool GetIsResizable(UIElement d)
        {
            return (bool) d.GetValue(IsResizableProperty);
        }

        #endregion
    }

    public class ZObjectResizingInformation
    {
        public List<TouchEventArgs> ContactEvents;

        public FrameworkElement ElementBeingResized;
        public ManipulationProcessor2D ManipulationProcessor;
        public List<ZInformationLandscape> ParentLandscapes;

        public ZObjectResizingInformation(FrameworkElement element)
        {
            ElementBeingResized = element;
            ManipulationProcessor = new ManipulationProcessor2D(Manipulations2D.Scale | Manipulations2D.TranslateX | Manipulations2D.TranslateY);
            ContactEvents = new List<TouchEventArgs>();
        }

        public double getScaleFactor()
        {
            if (ParentLandscapes == null)
            {
                return 1.0;
            }
            else
            {
                double scale = 1.0;
                foreach (ZInformationLandscape landscape in ParentLandscapes)
                {
                    scale *= landscape.Animation.Position.Zoom;
                }
                return scale;
            }
        }
    }

    public class ZObjectResizeAdorner : ZComponentAdorner
    {
        private Thumb _bottomLeftThumb;
        private Thumb _bottomRightThumb;
        private Thumb _bottomThumb;
        private double _currentAdornedElementHeight;
        private double _currentAdornedElementWidth;
        private bool _isVisible = true;
        private Thumb _leftThumb, _rightThumb;

        private double _scaleFactor;

        private double _thumbSize = 10.0;
        private Thumb _topLeftThumb;
        private Thumb _topRightThumb;
        private Thumb _topThumb;

        #region constructor

        public ZObjectResizeAdorner(ZComponent elem)
            : base(elem)
        {
            // find parent landscape to get current scalefactor
            ZTreeHelper.TryFindParent<ZInformationLandscape>(elem).Animation.Changed += Animation_Changed;

            _scaleFactor = ZTreeHelper.TryFindParent<ZInformationLandscape>(elem).Animation.Position.Zoom;

            #region calculate current AdornedElement-Size, that Thumbs are only visible if AdornerElement is large enough

            AdornerLayer layer = AdornerLayer.GetAdornerLayer(AdornedElement);
            _currentAdornedElementWidth = AdornedElement.DesiredSize.Width*_scaleFactor;
            _currentAdornedElementHeight = AdornedElement.DesiredSize.Height*_scaleFactor;

            if ((_currentAdornedElementWidth < _thumbSize*4) || (_currentAdornedElementHeight < _thumbSize*4))
            {
                //initThumbs();
                layer.Remove(this);
                _isVisible = false;
                return;
            }
            else
            {
                _isVisible = true;
                initThumbs();
            }

            #endregion
        }

        /// <summary>
        ///     Initializes thumbs depending on current scalefactor
        /// </summary>
        private void initThumbs()
        {
            _rightThumb = getAdornerCorner(Cursors.SizeWE, _thumbSize/_scaleFactor, AdornedElement.DesiredSize.Height);
            _leftThumb = getAdornerCorner(Cursors.SizeWE, _thumbSize/_scaleFactor, AdornedElement.DesiredSize.Height);
            _bottomThumb = getAdornerCorner(Cursors.SizeNS, AdornedElement.DesiredSize.Width, _thumbSize/_scaleFactor);
            _topThumb = getAdornerCorner(Cursors.SizeNS, AdornedElement.DesiredSize.Width, _thumbSize/_scaleFactor);

            _bottomRightThumb = getAdornerCorner(Cursors.SizeNWSE, _thumbSize/_scaleFactor, _thumbSize/_scaleFactor);
            _bottomLeftThumb = getAdornerCorner(Cursors.SizeNESW, _thumbSize/_scaleFactor, _thumbSize/_scaleFactor);
            _topRightThumb = getAdornerCorner(Cursors.SizeNESW, _thumbSize/_scaleFactor, _thumbSize/_scaleFactor);
            _topLeftThumb = getAdornerCorner(Cursors.SizeNWSE, _thumbSize/_scaleFactor, _thumbSize/_scaleFactor);

            AddChild(_rightThumb, AdornerPlacement.In, AdornerPosition.RightEdge, 0, 0);
            AddChild(_leftThumb, AdornerPlacement.In, AdornerPosition.LeftEdge, 0, 0);

            AddChild(_bottomThumb, AdornerPlacement.In, AdornerPosition.BottomEdge, 0, 0);
            AddChild(_topThumb, AdornerPlacement.In, AdornerPosition.TopEdge, 0, 0);

            AddChild(_bottomRightThumb, AdornerPlacement.In, AdornerPosition.BottomRightcorner);
            AddChild(_bottomLeftThumb, AdornerPlacement.In, AdornerPosition.BottomLeftCorner);

            AddChild(_topRightThumb, AdornerPlacement.In, AdornerPosition.TopRightCorner);
            AddChild(_topLeftThumb, AdornerPlacement.In, AdornerPosition.TopLeftCorner);

            _rightThumb.DragDelta += HandleRight;
            _bottomThumb.DragDelta += HandleBottom;
            _bottomRightThumb.DragDelta += HandleBottomRight;
            _leftThumb.DragDelta += HandleLeft;
            _bottomLeftThumb.DragDelta += HandleBottomLeft;
            _topLeftThumb.DragDelta += HandleTopLeft;
            _topThumb.DragDelta += HandleTop;
            _topRightThumb.DragDelta += HandleTopRight;
        }

        /// <summary>
        ///     if Landscape-Animations changes, size of thumbs get reset
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Animation_Changed(object sender, ZLandscapeAnimationEventArgs e)
        {
            // get current scalefactor if Animation exists:
            var zil = ZTreeHelper.TryFindParent<ZInformationLandscape>(AdornedElement);

            if (zil != null)
            {
                _scaleFactor = zil.Animation.Position.Zoom;

                _currentAdornedElementWidth = AdornedElement.DesiredSize.Width*_scaleFactor;
                _currentAdornedElementHeight = AdornedElement.DesiredSize.Height*_scaleFactor;

                AdornerLayer layer = AdornerLayer.GetAdornerLayer(AdornedElement);

                // if AdornedElement is not large enough, remove adorner from AdornerLayer
                if (((_currentAdornedElementWidth < _thumbSize*4) || (_currentAdornedElementHeight < _thumbSize*4)))
                {
                    layer.Remove(this);
                    _isVisible = false;
                    return;
                }

                // if AdornedElement is now large enough and AdornerLayer does not contain adorner, add it.
                if (!_isVisible)
                {
                    if (!layer.GetAdorners(AdornedElement).Contains(this))
                    {
                        layer.Add(this);
                    }
                    _isVisible = true;
                }

                //HACK: if thumbs are not set, initialize them
                if (_topThumb == null)
                {
                    initThumbs();
                }

                #region set size of thumbs depending on current scalefactor

                _topLeftThumb.Width = _thumbSize/_scaleFactor;
                _rightThumb.Width = _thumbSize/_scaleFactor;
                _leftThumb.Width = _thumbSize/_scaleFactor;
                _bottomRightThumb.Width = _thumbSize/_scaleFactor;
                _bottomLeftThumb.Width = _thumbSize/_scaleFactor;
                _topLeftThumb.Width = _thumbSize/_scaleFactor;
                _topRightThumb.Width = _thumbSize/_scaleFactor;

                _topLeftThumb.Height = _thumbSize/_scaleFactor;
                _bottomThumb.Height = _thumbSize/_scaleFactor;
                _bottomRightThumb.Height = _thumbSize/_scaleFactor;
                _bottomLeftThumb.Height = _thumbSize/_scaleFactor;
                _topLeftThumb.Height = _thumbSize/_scaleFactor;
                _topThumb.Height = _thumbSize/_scaleFactor;
                _topRightThumb.Height = _thumbSize/_scaleFactor;

                _rightThumb.Height = AdornedElement.DesiredSize.Height;
                _leftThumb.Height = AdornedElement.DesiredSize.Height;

                _bottomThumb.Width = AdornedElement.DesiredSize.Width;
                _topThumb.Width = AdornedElement.DesiredSize.Width;

                #endregion
            }
        }

        #endregion

        #region Visual Property Setters

        private void AddToWidth(Thumb thumb, double diff)
        {
            var adornedElement = AdornedElement as FrameworkElement;
            if (adornedElement == null)
            {
                return;
            }
            adornedElement.Width = Math.Max(adornedElement.Width + diff, thumb.DesiredSize.Width);
        }

        private void AddToHeight(Thumb thumb, double diff)
        {
            var adornedElement = AdornedElement as FrameworkElement;
            if (adornedElement == null)
            {
                return;
            }
            adornedElement.Height = Math.Max(adornedElement.Height + diff, thumb.DesiredSize.Height);
        }

        private void AddToLeft(double diff)
        {
            var adornedElement = AdornedElement as FrameworkElement;
            if (adornedElement == null)
            {
                return;
            }
            Canvas.SetLeft(adornedElement, Canvas.GetLeft(adornedElement) + diff);
        }

        private void AddToTop(double diff)
        {
            var adornedElement = AdornedElement as FrameworkElement;
            if (adornedElement == null)
            {
                return;
            }
            Canvas.SetTop(adornedElement, Canvas.GetTop(adornedElement) + diff);
        }

        #endregion

        #region Event Handling

        private void HandleLeft(object sender, DragDeltaEventArgs args)
        {
            var hitThumb = sender as Thumb;

            if (hitThumb == null)
            {
                return;
            }

            EnforceSize();

            AddToWidth(hitThumb, -args.HorizontalChange);
            AddToLeft(args.HorizontalChange);
        }

        private void HandleBottomLeft(object sender, DragDeltaEventArgs args)
        {
            var hitThumb = sender as Thumb;

            if (hitThumb == null)
            {
                return;
            }

            EnforceSize();

            AddToWidth(hitThumb, -args.HorizontalChange);
            AddToHeight(hitThumb, args.VerticalChange);
            AddToLeft(args.HorizontalChange);
        }

        private void HandleTopLeft(object sender, DragDeltaEventArgs args)
        {
            var hitThumb = sender as Thumb;

            if (hitThumb == null)
            {
                return;
            }

            EnforceSize();

            AddToWidth(hitThumb, -args.HorizontalChange);
            AddToHeight(hitThumb, -args.VerticalChange);
            AddToLeft(args.HorizontalChange);
            AddToTop(args.VerticalChange);
        }

        private void HandleTop(object sender, DragDeltaEventArgs args)
        {
            var hitThumb = sender as Thumb;

            if (hitThumb == null)
            {
                return;
            }

            EnforceSize();

            AddToHeight(hitThumb, -args.VerticalChange);
            AddToTop(args.VerticalChange);
        }

        private void HandleTopRight(object sender, DragDeltaEventArgs args)
        {
            var hitThumb = sender as Thumb;

            if (hitThumb == null)
            {
                return;
            }

            EnforceSize();

            AddToWidth(hitThumb, args.HorizontalChange);
            AddToHeight(hitThumb, -args.VerticalChange);
            AddToTop(args.VerticalChange);
        }

        private void HandleRight(object sender, DragDeltaEventArgs args)
        {
            var hitThumb = sender as Thumb;

            if (hitThumb == null)
            {
                return;
            }

            EnforceSize();

            AddToWidth(hitThumb, args.HorizontalChange);
        }

        private void HandleBottom(object sender, DragDeltaEventArgs args)
        {
            var hitThumb = sender as Thumb;

            if (hitThumb == null)
            {
                return;
            }

            EnforceSize();

            AddToHeight(hitThumb, args.VerticalChange);
        }

        private void HandleBottomRight(object sender, DragDeltaEventArgs args)
        {
            var hitThumb = sender as Thumb;

            if (hitThumb == null)
            {
                return;
            }

            EnforceSize();

            AddToWidth(hitThumb, args.HorizontalChange);
            AddToHeight(hitThumb, args.VerticalChange);
        }

        #endregion

        #region private helper methods

        private Thumb getAdornerCorner(Cursor customizedCursor, double w, double h)
        {
            var cornerThumb = new Thumb();
            cornerThumb.Cursor = customizedCursor;
            cornerThumb.Width = (w < 0 ? 0 : w);
            cornerThumb.Height = (h < 0 ? 0 : h);
            cornerThumb.Opacity = 0;

            return cornerThumb;
        }

        private void EnforceSize()
        {
            var adornedElement = AdornedElement as FrameworkElement;

            if (adornedElement == null)
            {
                return;
            }

            if (adornedElement.Width.Equals(Double.NaN))
            {
                adornedElement.Width = adornedElement.DesiredSize.Width;
            }
            if (adornedElement.Height.Equals(Double.NaN))
            {
                adornedElement.Height = adornedElement.DesiredSize.Height;
            }

            var parent = adornedElement.Parent as FrameworkElement;
            if (parent != null)
            {
                adornedElement.MaxHeight = parent.ActualHeight;
                adornedElement.MaxWidth = parent.ActualWidth;
            }
        }

        #endregion

        #region Adorner overrides

        ////TODO: check if this method is necessary 
        //protected override Size ArrangeOverride(Size finalSize)
        //{
        //    double desiredWidth = Math.Max(AdornedElement.DesiredSize.Width, 20.0);
        //    double desiredHeight = Math.Max(AdornedElement.DesiredSize.Height, 20.0);
        //    double adornerWidth = this.DesiredSize.Width;
        //    double adornerHeight = this.DesiredSize.Height;

        //    base.ArrangeOverride(finalSize);

        //    _rightThumb.Arrange(new Rect(desiredWidth - 10, 10, 10, desiredHeight - 20));
        //    _bottomThumb.Arrange(new Rect(10, desiredHeight - 10, desiredWidth - 20, 10));
        //    _bottomRightThumb.Arrange(new Rect(desiredWidth - 10, desiredHeight - 10, 10, 10));
        //    _leftThumb.Arrange(new Rect(0, 10, 10, desiredHeight - 20));
        //    _bottomLeftThumb.Arrange(new Rect(0, desiredHeight - 10, 10, 10));
        //    _topLeftThumb.Arrange(new Rect(0, 0, 10, 10));
        //    _topThumb.Arrange(new Rect(10, 0, desiredWidth - 20, 10));
        //    _topRightThumb.Arrange(new Rect(desiredWidth - 10, 0, 10, 10));

        //    return finalSize;
        //}

        //protected override int VisualChildrenCount
        //{
        //    get
        //    {
        //        return visualChildren.Count;
        //    }
        //}

        //protected override Visual GetVisualChild(int index)
        //{
        //    return visualChildren[index];
        //}

        #endregion
    }
}